package cn.edu.ujs.coor.service;

import cn.edu.ujs.coor.common.exception.CoorException;
import cn.edu.ujs.coor.common.oss.service.OssService;
import cn.edu.ujs.coor.model.*;
import cn.edu.ujs.coor.repository.field.FieldRepository;
import cn.edu.ujs.coor.repository.item.ItemMapper;
import cn.edu.ujs.coor.repository.item.ItemRepository;
import cn.edu.ujs.coor.repository.project.ProjectMapper;
import cn.edu.ujs.coor.repository.project.ProjectRepository;
import cn.edu.ujs.coor.repository.relation.GroupUserRelationRepository;
import cn.edu.ujs.coor.repository.relation.ProjectGroupRelationRepository;
import cn.edu.ujs.coor.repository.relation.ProjectUserRelationRepository;
import cn.edu.ujs.coor.repository.user.UserRepository;
import cn.edu.ujs.coor.request.IdRequest;
import cn.edu.ujs.coor.request.project.ProjectAddRequest;
import cn.edu.ujs.coor.request.project.ProjectPageRequest;
import cn.edu.ujs.coor.request.project.ProjectSubmitRequest;
import cn.edu.ujs.coor.request.project.ProjectUpdateRequest;
import cn.edu.ujs.coor.response.ItemResponse;
import cn.edu.ujs.coor.response.PageResponse;
import cn.edu.ujs.coor.response.ProjectResponse;
import cn.edu.ujs.coor.util.BeanUtil;
import cn.edu.ujs.coor.util.ExcelUnit;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 项目Service
 *
 * @author 柳曾雄
 * @date 2018-07-31
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ProjectService extends BaseService<Project, ProjectResponse> {

    @Autowired
    private ProjectUserRelationRepository userRelationRepository;

    @Autowired
    private ProjectGroupRelationRepository groupRelationRepository;

    @Autowired
    private GroupUserRelationRepository groupUserRelationRepository;

    @Autowired
    private ItemRepository itemRepository;

    @Autowired
    private ItemMapper itemMapper;

    @Autowired
    private FieldRepository fieldRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OssService ossService;

    @Autowired
    private MessageService messageService;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Autowired
    public void setMapper(ProjectMapper mapper) {
        this.mapper = mapper;
    }

    @Autowired
    public void setRepository(ProjectRepository repository) {
        this.repository = repository;
    }

    public ProjectResponse info (IdRequest request, User user) {
        Item item = itemRepository.findByProjectIdAndUserId(request.getId(), user.getId());
        ProjectResponse response = new ProjectResponse();
        BeanUtil.copyBeanIgnoreNull(response, this.findById(request.getId()));
        response.setCount(itemRepository.findByProjectId(request.getId()).size() + "");
        response.setUserIds(userRelationRepository.findUserByProjectId(request.getId()));
        response.setGroupIds(groupRelationRepository.findGroupByProjectId(request.getId()));
        response.setFields(fieldRepository.findByProjectIdOrderBySortAsc(request.getId()));
        if (item != null) {
            response.setContent(item.getContent());
        }
        return response;
    }

    /**
     * 新建项目
     * @param request
     */
    public void create (ProjectAddRequest request) {
        // 创建项目
        Project project = Project.builder().status("0").build();
        BeanUtil.copyBeanIgnoreNull(project, request);
        repository.save(project);

        // 计算协同人数
        Set<String> ids = new HashSet<>();

        // 关联用户
        if (request.getUserIds() != null && request.getUserIds().size() > 0) {
            ids.addAll(request.getUserIds());
            for (String userId : request.getUserIds()) {
                ProjectUserRelation relation = ProjectUserRelation
                        .builder()
                        .projectId(project.getId())
                        .userId(userId)
                        .build();
                userRelationRepository.save(relation);
            }
        }
        // 关联分组
        if (request.getGroupIds() != null && request.getGroupIds().size() > 0) {
            for (String groupId : request.getGroupIds()) {
                // 分组协同
                ids.addAll(groupUserRelationRepository.findByGroupId(groupId));
                // 项目分组关联
                ProjectGroupRelation relation = ProjectGroupRelation
                        .builder()
                        .projectId(project.getId())
                        .groupId(groupId)
                        .build();
                groupRelationRepository.save(relation);
            }
        }
        // 发送协同消息
        messageService.add("协同项目【参与】提示",
                String.format("您已被纳入协同项目【%s】参与者，截止时间【%s】，请及时提交", project.getName(), sdf.format(project.getDeadline())), new ArrayList<>(ids));
        project.setSum(ids.size() + "");
        this.save(project);
    }

    public void update (ProjectUpdateRequest request) {
        Project project = this.findById(request.getId());
        if (project == null) {
            throw new CoorException("er_000002", "该项目不存在");
        }
        // 更新项目信息
        BeanUtil.copyBeanIgnoreNull(project, request);

        // 计算协同人数
        Set<String> ids = new HashSet<>();

        // 更新关联用户
        userRelationRepository.deleteByProjectId(project.getId());
        if (request.getUserIds() != null && request.getUserIds().size() > 0) {
            ids.addAll(request.getUserIds());
            for (String userId : request.getUserIds()) {
                ProjectUserRelation relation = ProjectUserRelation
                        .builder()
                        .projectId(project.getId())
                        .userId(userId)
                        .build();
                userRelationRepository.save(relation);
            }
        }
        // 关联更新分组
        groupRelationRepository.deleteByProjectId(project.getId());
        if (request.getGroupIds() != null && request.getGroupIds().size() > 0) {
            for (String groupId : request.getGroupIds()) {
                // 分组协同人数
                ids.addAll(groupUserRelationRepository.findByGroupId(groupId));
                ProjectGroupRelation relation = ProjectGroupRelation
                        .builder()
                        .projectId(project.getId())
                        .groupId(groupId)
                        .build();
                groupRelationRepository.save(relation);
            }
        }
        // 协同消息提示
        messageService.add("协同项目【参与】提示",
                String.format("您已被纳入协同项目【%s】参与者，截止时间【%s】，请及时提交", project.getName(), sdf.format(project.getDeadline())), new ArrayList<>(ids));
        project.setSum(ids.size() + "");
        save(project);
    }

    /**
     * 参与的项目
     * @param request
     * @return
     */
    public PageResponse<ProjectResponse> pageByActor (ProjectPageRequest request) {
        Page<ProjectResponse> result = ((ProjectMapper)mapper).pageByActor(request, new RowBounds(request.getIndex(), request.getSize()));
        return new PageResponse<ProjectResponse>(result.getResult(), request, result.getTotal());
    }

    /**
     * 删除项目
     * @param request
     */
    public void delete (IdRequest request) {
        Project project = this.findById(request.getId());
        if (project == null) {
            throw new CoorException("er_000002", "该项目不存在");
        }
        // 删除项目关联
        userRelationRepository.deleteByProjectId(project.getId());
        groupRelationRepository.deleteByProjectId(project.getId());
        // 删除项目记录
        this.delete(project);
    }

    /**
     * 项目完结
     * @param request
     */
    public void complete (IdRequest request) {
        Project project = this.findById(request.getId());
        if (project == null) {
            throw new CoorException("项目不存在");
        }
        if ("1".equals(project.getStatus())) {
            throw new CoorException("项目已完结");
        }
        Set<String> ids = new HashSet<>();
        ids.addAll(userRelationRepository.findUserByProjectId(project.getId()));
        List<String> groupIds = groupRelationRepository.findGroupByProjectId(project.getId());
        for (String groupId : groupIds) {
            ids.addAll(groupUserRelationRepository.findByGroupId(groupId));
        }
        // 协同消息提示
        messageService.add("协同项目【完结】提示",
                String.format("您参与的协同项目【%s】已完结，请知晓！", project.getName()), new ArrayList<>(ids));
        // 负责人提示
        messageService.add("协同项目【完结】提示",
                String.format("您参与的协同项目【%s】已完结，请知晓！", project.getName()), project.getUserId());
        project.setStatus("1");
        this.save(project);
    }

    /**
     * 项目内容提交
     */
    public void submit (ProjectSubmitRequest request) {
        Project project = this.findById(request.getProjectId());
        if (project == null) {
            throw new CoorException("项目不存在");
        }
        if ("1".equals(project.getStatus())) {
            throw new CoorException("项目已完结");
        }
        Item temp = itemRepository.findByProjectIdAndUserId(request.getProjectId(), request.getUserId());
        if (temp == null) {
            Item item = Item.builder().build();
            BeanUtil.copyBeanIgnoreNull(item, request);
            itemRepository.save(item);
            return;
        }
        BeanUtil.copyBeanIgnoreNull(temp, request);
        User user = userRepository.findById(request.getUserId()).orElse(null);
        // 协同消息提示
        messageService.add("协同项目【提交】提示",
                String.format("您参与的协同项目【%s】已成功提交，请关注相关动态！", project.getName()), request.getUserId());
        // 负责人提示
        messageService.add("协同项目【提交】提示",
                String.format("协同成员【%s】已提交数据至协同项目【%s】，请及时查看！", user.getName(), project.getName()), project.getUserId());
        itemRepository.save(temp);
    }

    /**
     * 导出数据
     * @param id
     * @return
     */
    public ByteArrayOutputStream export (String id) {
        Project project = this.findById(id);
        if (project == null) {
            throw new CoorException("项目不存在");
        }
        if ("1".equals(project.getType())) {
            List<String> items = itemRepository.findContentByProjectId(id);
            return ossService.get(items);
        }

        List<Field> list = fieldRepository.findByProjectIdOrderBySortAsc(id);

        List<NameValuePair> pairs = new ArrayList<>();
        for (Field field : list) {
            NameValuePair pair = new BasicNameValuePair(field.getName(), field.getId());
            pairs.add(pair);
        }
        pairs.add(new BasicNameValuePair("提交人", "userName"));


        List<ItemResponse> items = itemMapper.list(id);
        List<Map<String, Object>> data = new ArrayList<>();
        for (ItemResponse item : items) {
            Map temp = (Map) JSON.parse(item.getContent());
            temp.put("userName", item.getUserName());
            data.add(temp);
        }

        return ExcelUnit.export(pairs, data);
    }

    public List<Project> findNearDeadline (Integer diff) {
        return ((ProjectRepository) repository).findNearDeadline(diff);
    }

    public List<Project> findDeadlined () {
        return ((ProjectRepository) repository).findDeadlined();
    }
}